package com.glzn.springboot03.service.impl;


import com.glzn.springboot03.entity.WaveHead;
import com.glzn.springboot03.mapper.WaveMapper;
import com.glzn.springboot03.mqtt.MqttPublishClient;
import com.glzn.springboot03.service.WaveService;
import com.glzn.springboot03.util.ComService;
import com.glzn.springboot03.util.VeDate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.*;

/**
 * @author Administrator
 */
@Service
public class WaveServiceImpl implements WaveService {
	private final static Logger logger = LoggerFactory.getLogger(EventServiceImpl.class);

	private final static int ONE_FRAME_MAX_SUMMARY_COUNT = 28;

	private final static int BLOCK_SIZE = 512;

	private Map<String, Integer> map = new HashMap<>();

	@Autowired
	private WaveMapper waveMapper;

	@Override
	public List<WaveHead> findAll(Integer deviceId) {
		return waveMapper.findAll(deviceId);
	}

	@Override
	public WaveHead findById(int id, Integer deviceId) {
		return waveMapper.findById(id, deviceId);
	}

	@Override
	public boolean insert(WaveHead waveHead) {
		return waveMapper.insert(waveHead);
	}

	@Override
	public boolean deleteAll(Integer deviceId) {
		return waveMapper.deleteAll(deviceId);
	}

	@Override
	public int getProcess(String sessionId) {
		Integer process = map.get(sessionId);
		if (process == null) {
			process = 0;
		}
		if (process == 100){
			map.remove(sessionId);
		}
		return process;
	}

	@Override
	public String listWaveHead(){
		HttpSession session = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getSession();
		MqttPublishClient mqttPublishClient = (MqttPublishClient) session.getAttribute("mqttPublishClient");
		Integer deviceId = (Integer) session.getAttribute("device_id");
		String sessionId = session.getId();

		if (mqttPublishClient == null) {
			return "device";
		}
		int process = 0;

		ComService comService = new ComService();
		comService.setServerType(0x1);
		comService.setCmd(0x71);

		//获取数据
		byte[] data = mqttPublishClient.sendAndRecv(comService, 1000*20, false);
		if(null == data){
			return "failed";
		}
		//解析数据
		List<WaveHead> waveHeads = new ArrayList<>();
		int count = data[7];
		int pos = 8;
		int len = 32;

		int nReCnt = ((count%ONE_FRAME_MAX_SUMMARY_COUNT) == 0)?(count/ONE_FRAME_MAX_SUMMARY_COUNT):((count/ONE_FRAME_MAX_SUMMARY_COUNT)+1);
		int curCount = 0;
		int cmd = 0x71;
		for (int j = 0; j < nReCnt; j++){
			if (j != 0){
				pos = 8;
				comService.setServerType(0x1);
				comService.setCmd(cmd);
				data = mqttPublishClient.sendAndRecv(comService, 1000*20, false);
				int errTimes = 0;
				while (null == data){
					errTimes++;
					if(errTimes > 3) {
						return "failed";
					}
					data = mqttPublishClient.sendAndRecv(comService, 1000*20, true);
				}
			}
			curCount = count - j*ONE_FRAME_MAX_SUMMARY_COUNT;
			if (curCount > ONE_FRAME_MAX_SUMMARY_COUNT){
				curCount = ONE_FRAME_MAX_SUMMARY_COUNT;
			}
			for (int i=0; i<curCount; i++){
				try {
					String type = new String(data, pos, len, "gbk");
					type = type.replaceAll("\u0000","");
					logger.info("index:{},type:{}", i, type);
					pos += len;
					//日期
					int year = 100+data[pos++];
					int month = data[pos++];
					int day = data[pos++];
					int hrs = data[pos++];
					int min = data[pos++];
					int sec = data[pos++];
					int millsecond = ((data[pos + 1] & 0xFF) << 8) | (data[pos]&0xFF);
					Date date = new Date(year, month - 1, day, hrs, min, sec);
					logger.info("date:{}", date);
					pos+=2;
					//进度
					process = 100*i/curCount/nReCnt + j*100/nReCnt;
					map.put(sessionId, process);
					WaveHead waveHead = new WaveHead(i, type, date, millsecond, deviceId);
					waveHeads.add(waveHead);
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
			}
			cmd+=0x10;
		}
		//保存到数据库
		deleteAll(deviceId);
		for (WaveHead waveHead : waveHeads) {
			insert(waveHead);
		}
		process = 100;
		map.put(sessionId, process);
		return "success";
	}

	@Override
	public String listWave(List<WaveHead> waveHeadList){
		HttpSession session = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getSession();
		MqttPublishClient mqttPublishClient = (MqttPublishClient) session.getAttribute("mqttPublishClient");
		String sessionId = session.getId();

		if (mqttPublishClient == null) {
			return "device";
		}
		int process = 0;
		for (int i=0; i< waveHeadList.size(); i++) {
			WaveHead waveHead = waveHeadList.get(i);
			int pieceNum = 0;
			int pos = 7;
			int fileLength = 0;
			byte[] waveData = null;
			do {
				pos = 7;
				ComService comService = new ComService();
				comService.setServerType(0x1);
				comService.setPieceNum(pieceNum);
				comService.setStartType(waveHead.getType());
				comService.setHappenTime(VeDate.dateToStrLong(waveHead.getHappenTime()));
				comService.setMillsecond(waveHead.getMillsecond());
				comService.setCmd(0x72);
				//获取数据
				byte[] data1 = mqttPublishClient.sendAndRecv(comService, 1000*20, false);
				int errTimes = 0;
				while(null == data1){
					errTimes++;
					if(errTimes > 3) {
						return "failed";
					}
					data1 = mqttPublishClient.sendAndRecv(comService, 1000*20, true);
				}
				//解析数据
				pieceNum = ((data1[pos+1] & 0xFF) << 8) | (data1[pos] & 0xFF);
				logger.info("pieceNum:{}", pieceNum);
				pos+=2;
				//文件长度
				if(fileLength == 0){
					fileLength = ((data1[pos+3] & 0xFF) << 24) | ((data1[pos+2] & 0xFF)<<16) | ((data1[pos+1] & 0xFF) << 8) | (data1[pos] & 0xFF);
					logger.info("file length:{}", fileLength);
					waveData = new byte[fileLength];
				}
				pos+=4;
				//data 接收的长度-15
				if ((pieceNum+1)*BLOCK_SIZE>fileLength){
					System.arraycopy(data1, pos, waveData, pieceNum*BLOCK_SIZE, fileLength - pieceNum*BLOCK_SIZE);
				}else {
					System.arraycopy(data1, pos, waveData, pieceNum*BLOCK_SIZE, data1.length - 15);
				}
				pieceNum++;
				//进度
				process = 100*pieceNum*BLOCK_SIZE/fileLength/waveHeadList.size() + i*100/waveHeadList.size();
				map.put(sessionId, process);
			}while (pieceNum * BLOCK_SIZE < fileLength);
			//保存文件
			String filepath = waveHead.getType()+"("+VeDate.dateToStrLong(waveHead.getHappenTime()).replaceAll(":", "_")+"-"+ waveHead.getMillsecond() +").wave";
			saveFile(waveData, 0, waveData.length, filepath);
		}
		process = 100;
		map.put(sessionId, process);
		return "success";
	}

	public void saveFile(byte[] b, int off, int len, String filepath){
		try {
			FileOutputStream fileOutputStream = new FileOutputStream(filepath);
			fileOutputStream.write(b, off, len);
			fileOutputStream.flush();
			fileOutputStream.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}
